package com.ls.order.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.ls.common.annotation.Idempotent;
import com.ls.common.config.AlipayConfig;
import com.ls.common.util.TokenUtil;
import com.ls.order.pojo.dto.OrderDTO;
import com.ls.order.pojo.entity.Order;
import com.ls.order.service.AliPayService;
import com.ls.order.service.IOrderService;
import com.ls.common.entity.Result;
import com.ls.product.client.ProductFeignClient;
import com.ls.product.pojo.entity.Product;
import com.ls.user.pojo.client.UserFeignClient;
import com.ls.user.pojo.entity.User;
import com.ls.user.pojo.entity.UserScore;
import io.jsonwebtoken.lang.Assert;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author xiaotang
 * @since 2023-04-07
 */
@RestController
@RequestMapping("/order")
public class OrderController {

//    @Autowired
//    RestTemplate restTemplate;

    @Autowired
    DiscoveryClient discoveryClient;

    @Autowired
    private IOrderService orderService;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    AliPayService aliPayService;


    @Autowired
    UserFeignClient userFeignClient;

    @Autowired
    AlipayConfig alipayConfig;


    @GetMapping("/getOrderById/{id}")
    @ApiOperation("根据id查找订单")
    public Result getOrderById(@PathVariable Integer id){
        Order order = orderService.getById(id);
        return new Result(200, "查找成功", order);
    }

    @DeleteMapping("/removeOrder")
    @ApiOperation("删除订单")
    public Result removeOrder(@PathVariable Integer id){
        boolean flag = orderService.removeById(id);
        return flag ? new Result(200, "删除成功") : new Result(500, "删除失败");
    }

    @PostMapping("addOrUpdateOrder")
    @ApiOperation("添加或者修改订单")
    public Result addOrUpdateOrder(@RequestBody Order order){
        Boolean flag = orderService.saveOrUpdate(order);
        return flag ? new Result(200, "操作成功") : new Result(500, "操作失败");
    }


    @PostMapping("/preyOrder")
    @ApiOperation("预下单")
//    @Idempotent
    public Result buyProduct(@RequestBody OrderDTO orderDTO) throws Exception {
        Assert.notNull(orderDTO, "参数为空");
        //1、判断商品是否存在
        Result<Product> product = productFeignClient.getProduct(orderDTO.getProductId());
        Product productData = product.getData();
        Result<Integer> row = null;
        String qrCode = null;
        //2、商品存在且库存大于0，库存是否大于0
        if (productData != null && productData.getStock() > 0) {
            Order order = new Order();
            BeanUtils.copyProperties(orderDTO,order);
            //设置订单单价和总价
            order.setPrice(productData.getPrice());
            order.setAmount(productData.getPrice().multiply(new BigDecimal(orderDTO.getNumber())));
            //库存-1
            row = productFeignClient.updateProduct(orderDTO.getProductId());
            //生成一个订单号
            String tradeOutNo = UUID.randomUUID().toString().replace("-", "");
            order.setTradeOutNo(tradeOutNo);
            //生成订单
            orderService.save(order);

            //预下单并且生成二维码
            qrCode = aliPayService.preCreate(order.getId(), orderDTO.getUserId());
        }
        //返回二维码
        return qrCode != null ? new Result(200, "预下单成功", qrCode) : new Result(500, "预下单失败");
    }

    @ApiOperation("支付通知")
    @PostMapping("/notify")
    public void nativeNotify(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException, IOException {

        Map<String,String> params = new HashMap<>();
        Map<String, String[]> parameterMap = request.getParameterMap();
        Iterator<String> iterator = parameterMap.keySet().iterator();
        while (iterator.hasNext()){
            String name = iterator.next();
            String[] strings = parameterMap.get(name);
            String str = "";
            for(int i = 0; i < strings.length; i++){
                str = (i == strings.length - 1) ? str + strings[i] : str + strings[i] + ",";
            }
            params.put(name, str);
        }
        String userId1 = params.get("userId");
        Integer userId = 1;

        boolean sign =  AlipaySignature.rsaCheckV1(params, alipayConfig.getPublic_key(), alipayConfig.getCharset(),alipayConfig.getSign_type());
        System.out.println(sign);

        //进行验签操作
        //验证订单号、金额、商户id、appid
        response.setContentType("text/html;charset=utf-8");
//        PrintWriter out = response.getWriter();
        if(sign){
            String out_trade_no = request.getParameter("out_trade_no");
            String trade_no = request.getParameter("trade_no");
            String trade_status = request.getParameter("trade_status");
            if(trade_status.equals("TRADE_SUCCESS")){
                System.out.println("交易完成");
//                out.println("success");
                Boolean userScoreFlag = null;
                    //根据用户id，查询用户信息
                    Result<User> userData = userFeignClient.getUserInfo(userId);
                    User user = userData.getData();

                    //根据用户id，查询用户积分信息
                    Result<UserScore> resultData = userFeignClient.getScoreByUserId(userId);
                    UserScore userScoreInfo = resultData.getData();
                    //填充用户积分信息
                    UserScore userScore = UserScore.builder()
                            .userId(user.getId())
                            .oldScore(user.getScore())
                            .description(user.getUsername() + "用户积分")
                            .createTime(LocalDateTime.now())
                            .action(2)
                            .build();
                    if(userScoreInfo == null){
                        //第一次，不存在用户积分信息
                        userScore.setOldScore(user.getScore());
                        userScore.setNewScore(user.getScore() + 10);
                    }else{
                        //已经存在用户积分信息
                        userScore.setId(userScoreInfo.getId());
                        userScore.setOldScore(userScoreInfo.getNewScore());
                        userScore.setNewScore(userScoreInfo.getNewScore() + 10);
                    }
                    //3、添加或者修改用户积分信息
                    Result<Boolean> userScoreData = userFeignClient.addOrUpdateUserScore(userScore);
                    userScoreFlag = userScoreData.getData();
            }else{
                System.out.println("交易失败");
//                out.println("fail");
            }
        }
    }

    @GetMapping("/getPayStatus")
    @ApiOperation("查询支付状态")
    @Transactional
    public Result getPayStatus(@RequestParam("tradeOutNo") String tradeOutNo, @RequestParam("userId") Integer userId) throws AlipayApiException {
        System.out.println("查询订单号是否完成支付");
        System.out.println(tradeOutNo);
        //1、查询订单支付状态
        boolean flag = aliPayService.query(tradeOutNo);
        Boolean userScoreFlag = null;
        //2、如果支付成功，修改用户积分
        if(flag){
            //根据用户id，查询用户信息
            Result<User> userData = userFeignClient.getUserInfo(userId);
            User user = userData.getData();

            //根据用户id，查询用户积分信息
            Result<UserScore> resultData = userFeignClient.getScoreByUserId(userId);
            UserScore userScoreInfo = resultData.getData();
            //填充用户积分信息
            UserScore userScore = UserScore.builder()
                    .userId(user.getId())
                    .oldScore(user.getScore())
                    .description(user.getUsername() + "用户积分")
                    .createTime(LocalDateTime.now())
                    .action(2)
                    .build();
                if(userScoreInfo == null){
                    //第一次，不存在用户积分信息
                    userScore.setOldScore(user.getScore());
                    userScore.setNewScore(user.getScore() + 10);
                }else{
                    //已经存在用户积分信息
                    userScore.setId(userScoreInfo.getId());
                    userScore.setOldScore(userScoreInfo.getNewScore());
                    userScore.setNewScore(userScoreInfo.getNewScore() + 10);
                }
            //3、添加或者修改用户积分信息
            Result<Boolean> userScoreData = userFeignClient.addOrUpdateUserScore(userScore);
            userScoreFlag = userScoreData.getData();
            return  new Result(200, "支付成功", flag);
        }
        return new Result(500, "支付失败", flag);
    }

    @GetMapping("/buy/{id}")
    @Idempotent
    public Result findById(@PathVariable Integer id) {
        synchronized (this) {
            //1、查询是否存在此商品
            Result<Product> product = productFeignClient.getProduct(id);
            Product productData = product.getData();
            Result<Integer> row = null;
            //2、商品存在且库存大于0
            if (productData != null && productData.getStock() > 0) {
                //生成订单

                //库存-1
                row = productFeignClient.updateProduct(id);
            }
            return row.getData() > 0 ? new Result(200, "购买成功") : new Result(200, "购买失败");
        }
    }

    @GetMapping("/createToken")
    @ApiOperation("order页面创建token")
    public Result createToken() {
        //1、工具类生成token
        String token = TokenUtil.creteToken();
        if (token == null) new Result(500, "创建token失败");
        //2将token存在redis
        redisTemplate.opsForValue().set("idempotent:" + token, token);
        //返回token给页面
        return new Result(200, "创建token成功", token);
    }


    //ribbon
//    @GetMapping("/buy/{id}")
//    public Result buy(@PathVariable Integer id){
//        Result result = restTemplate.getForObject("http://mall-product/product/" + id, Result.class);
//        return new Result(200, result.getMessage(), result.getData());
//    }


    //eureka
//    @GetMapping("/buy/{id}")
//    public Result buy(@PathVariable Integer id){
//        List<ServiceInstance> instances = discoveryClient.getInstances("mall-product");
//        if(instances.size() <= 0){
//            return new Result(500, "服务不可用");
//        }
//        ServiceInstance serviceInstance = instances.get(0);
//        String host = serviceInstance.getHost();
//        URI uri = serviceInstance.getUri();
//
//        int port = serviceInstance.getPort();
//        String requestUrl = "http://" +  host + ":" + port + "/product/" + id;
//        Result object = restTemplate.getForObject(requestUrl, Result.class);
//        return new Result(200, "sucess", object.getData());
//    }


    //restTemplate远程调用
//    @GetMapping("/buy/{id}")
//    public Result buy(@PathVariable Integer id){
//        // 1. 根据商品ID查询商品的信息
//        // 根据ID查询商品信息的访问地址为：http://localhost:8081/product/1，如果在代码中可以访问该地址，那么就可以拿到数据了
//        Result result = restTemplate.getForObject("http://localhost:8081/product/" + id, Result.class);
//        Object product = result.getData();
//        // 2. 进行下单操作 TODO
//        // 3. 响应结果
//        return new Result(200, "购买成功", product);
//    }
}
